package com.demo.gateway.filter.record;

import java.net.URI;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.util.Date;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import com.demo.gateway.pojo.RecordDO;
import com.demo.gateway.service.IRequestRecord;
import com.demo.gateway.util.JsonUtil;
import com.demo.gateway.util.RouteIdUtil;
import com.demo.gateway.util.UriUtil;

import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Mono;

/**
 * @author: demo
 * @date: 2020年7月2日
 * @Document : 请求记录过滤器
 */
@Slf4j
@Component
public class RecordGlobalFilter implements GlobalFilter, Ordered {
	@Autowired
	private IRequestRecord recordService;
	
	private  static  final   String  SUPPORT_SCHEME_HTTP="http";
	private  static  final   String  SUPPORT_SCHEME_HTTPS="https";

	@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		ServerHttpRequest originalRequest = exchange.getRequest();
		URI originalRequestUrl = originalRequest.getURI();
		// 只记录http的请求
		String scheme = originalRequestUrl.getScheme();
		if ((!SUPPORT_SCHEME_HTTP.equals(scheme) && !SUPPORT_SCHEME_HTTPS.equals(scheme))) {
			return chain.filter(exchange);
		}
		RecordDO record = new RecordDO(RouteIdUtil.nextStringId());
		Route  route=exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
		URI gatewayUri=route.getUri();
		record.setGatewayAddress(UriUtil.getUriAddress(gatewayUri));
		/**
		 * 重写request 和response
		 */
		RecordHttpRequestDecorator recordRequest = new RecordHttpRequestDecorator(exchange.getRequest());
		RecordHttpResponseDecorator recordResponse = new RecordHttpResponseDecorator(exchange.getResponse(), record,
				recordService);

		ServerWebExchange recordExchange = exchange.mutate().request(recordRequest).response(recordResponse).build();
		return recorderOriginalRequest( recordExchange, record).then(chain.filter(recordExchange)).then();
	}

	/**
	 * 记录请求信息
	 * 获取请求信息  ==>record
	 * url method header param startTime
	 * @param exchange
	 * @param record
	 * @return
	 */
	private Mono<Void> recorderOriginalRequest( ServerWebExchange exchange, RecordDO record) {
		ServerHttpRequest request = exchange.getRequest();
		URI requestUri=request.getURI();
		record.setUrl(requestUri.getRawPath());
		record.setRequestAddress(UriUtil.getUriAddress(requestUri));
		record.setMethod( request.getMethod().name());
		HttpHeaders headers = request.getHeaders();
		record.setClientAddress(RecordTool.getClientIp(request));
		record.setRequestHeader(JsonUtil.toString(headers));
		record.setStartTime(new Date());
		Charset requestCharset = RecordTool.getCharsetRecord(headers);
		Mono<Void> result =Mono.empty();
		try {
			log.info("请求信息==>{}",record);
			recordService.addRecord(record);
		} catch (Exception e) {
			log.error("record请求信息error !==>{}", e.getMessage());
		}
		if (requestCharset != null) {
		 result = DataBufferUtils.join(request.getBody()).doOnNext(buffer -> {
				CharBuffer charBuffer = requestCharset.decode(buffer.asByteBuffer());
				record.setRequestParam(charBuffer.toString());
				try {
					log.info("更新请求参数记录==>{}",record);
					recordService.updateRecordRequest(record);
				} catch (Exception e) {
					log.error("更新请求参数error !==>{}", e.getMessage());
				}
			
				DataBufferUtils.release(buffer);
			}).then();
		} 
		return result;
	}

	@Override
	public int getOrder() {
		return HIGHEST_PRECEDENCE;
	}

}